package com.dayu.finecomm.aop;

import io.netty.handler.codec.http.HttpContent;
import io.netty.handler.codec.http.HttpRequest;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;

import org.aopalliance.intercept.MethodInvocation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;

/**
 * AOP日志管理集中器
 * 
 * @author XuJialiang
 * @since 2017-11-10 14:45:12
 * @version V1.0.0
 */
@Component
public class AopLogManager {

	static Logger LOGGER = LoggerFactory.getLogger(AopLogManager.class);

	@Value("${mongodb.enable:false}")
	private boolean mongodbEnable = false;

	private BlockingQueue<AopLogItem> mLogQueue;

	public AopLogManager() {
		LOGGER.info("AopLogManager constructor");
	}

	public void init(BlockingQueue<AopLogItem> queue) {
		mLogQueue = queue;
	}

	/**
	 * 插入日志
	 * 
	 * @param invocation
	 * @param retVal
	 * @param reqTime
	 * @param rspTime
	 * @return
	 */
	public int insertAopLog(MethodInvocation invocation, Object retVal,
			Long reqTime, Long rspTime) {
		int result = -1;

		if (false == mongodbEnable) {
			return result;
		}

		try {
			AopLogItem item = new AopLogItem();

			MethodLevelAnnotation annotation = invocation.getMethod()
					.getAnnotation(MethodLevelAnnotation.class);

			Object[] objects = invocation.getArguments();

			String args = "";
			if (null != objects && 0 < objects.length) {
				for (Object obj : objects) {
					if (obj instanceof String || obj instanceof Integer
							|| obj instanceof Long || obj instanceof Double
							|| obj instanceof Boolean) {
						args += obj.toString() + "|";
					} else if (obj instanceof HttpRequest) {
						args += obj.toString() + "|";
						if (obj instanceof HttpContent) {
							args += ((HttpContent) obj).content().toString(
									io.netty.util.CharsetUtil.UTF_8)
									+ "|";
						}
					} else if (obj instanceof HttpContent) {
						args += ((HttpContent) obj).content().toString(
								io.netty.util.CharsetUtil.UTF_8)
								+ "|";
					} else {
						String jsonStr = checkParseJson(obj);
						if (null != jsonStr) {
							args += jsonStr + "|";
						} else {
							args += obj.toString() + "|";
						}
					}
				}

				args = args.substring(0, args.length() - 1);
			}

			String rsp = "";
			if (null != retVal) {
				if (retVal instanceof String || retVal instanceof Integer
						|| retVal instanceof Long || retVal instanceof Double
						|| retVal instanceof Boolean) {
					rsp += retVal.toString() + "|";
				} else {
					String jsonStr = checkParseJson(retVal);
					if (null != jsonStr) {
						rsp += jsonStr + "|";
					} else {
						rsp += retVal.toString() + "|";
					}
				}

				rsp = rsp.substring(0, rsp.length() - 1);
			}

			item.level = annotation.level().name();
			item.name = invocation.getMethod().getName();
			item.path = invocation.getThis().getClass().getName();
			item.args = args;
			item.result = rsp;
			item.reqTime = reqTime;
			item.rspTime = rspTime;
			item.consume = rspTime - reqTime;

			if (mLogQueue.offer(item, 50, TimeUnit.MILLISECONDS)) {
				result = 0;
			}
		} catch (Exception e) {
			LOGGER.error("insertAopLog error: " + e);
		}

		return result;
	}

	private String checkParseJson(Object obj) {
		String retStr = null;

		try {
			retStr = JSON.toJSONString(obj);
		} catch (Exception e) {
			retStr = null;
		}

		return retStr;
	}
}
